package com.ruoyi.setlanguages.until;

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.YouTubeScopes;
import org.springframework.stereotype.Component;

import java.io.*;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.List;


@Component
public class YouTubeAuth {
    private static final String APPLICATION_NAME = "RuoYi YouTube Manager";
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
    private static final String TOKENS_DIRECTORY_PATH = "tokens";
    private static final List<String> SCOPES =
            Collections.singletonList(YouTubeScopes.YOUTUBE);

    private static final String CREDENTIALS_FILE_PATH =
            "E:\\Yun\\RuoYi-Vue\\ruoyi-system\\src\\main\\resources\\doc\\client_secret_208331764780-chta2surkcj9ku18dhf3dhipr5fhvrv2.apps.googleusercontent.com.json";

    // 存储当前的Credential实例
    private static Credential currentCredential;
    private static YouTube currentYouTubeService;

    /**
     * 获取YouTube服务实例
     */
    public static YouTube getYouTubeService() throws IOException, GeneralSecurityException {
        if (currentYouTubeService == null) {
            initializeYouTubeService();
        }
        return currentYouTubeService;
    }

    /**
     * 初始化YouTube服务
     */
    private static void initializeYouTubeService() throws IOException, GeneralSecurityException {
        final NetHttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        currentCredential = authorize(httpTransport);
        currentYouTubeService = new YouTube.Builder(httpTransport, JSON_FACTORY, currentCredential)
                .setApplicationName(APPLICATION_NAME)
                .build();
        System.out.println("YouTube服务初始化完成");
    }

    /**
     * OAuth认证流程
     */
    private static Credential authorize(final NetHttpTransport HTTP_TRANSPORT) throws IOException {
        File credentialsFile = new File(CREDENTIALS_FILE_PATH);
        if (!credentialsFile.exists()) {
            throw new IOException("YouTube凭证文件未找到: " + CREDENTIALS_FILE_PATH);
        }

        System.out.println("正在加载YouTube凭证文件: " + credentialsFile.getAbsolutePath());

        InputStream in = new FileInputStream(credentialsFile);
        GoogleClientSecrets clientSecrets =
                GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));

        File tokenDir = new File(TOKENS_DIRECTORY_PATH);
        if (!tokenDir.exists()) {
            tokenDir.mkdirs();
        }

        GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
                HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
                .setDataStoreFactory(new FileDataStoreFactory(tokenDir))
                .setAccessType("offline")
                .build();

        LocalServerReceiver receiver = new LocalServerReceiver.Builder()
                .setPort(8888)
                .build();

        System.out.println("正在启动YouTube OAuth认证流程...");
        Credential credential = new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
        System.out.println("YouTube认证成功!");

        return credential;
    }

    /**
     * 清除凭证并重新初始化服务
     */
    public static YouTube clearAndReinitialize() throws IOException, GeneralSecurityException {
        System.out.println("开始清除YouTube凭证并重新初始化...");

        // 清除内存中的实例
        currentCredential = null;
        currentYouTubeService = null;

        // 清除磁盘上的令牌文件
        clearCredentials();

        // 重新初始化服务（这会触发新的OAuth流程）
        return getYouTubeService();
    }

    /**
     * 清除磁盘上的凭证文件
     */
    public static void clearCredentials() throws IOException {
        File tokenDir = new File(TOKENS_DIRECTORY_PATH);
        if (tokenDir.exists()) {
            deleteDirectory(tokenDir);
            System.out.println("YouTube凭证文件已清除");
        } else {
            System.out.println("未找到存储的YouTube凭证文件");
        }
    }

    /**
     * 检查凭证是否有效
     */
    public static boolean isCredentialValid() {
        try {
            if (currentCredential == null) {
                return false;
            }
            // 检查access token是否有效
            return currentCredential.getAccessToken() != null &&
                    !currentCredential.getExpiresInSeconds().equals(0L);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 获取当前认证状态
     */
    public static String getAuthStatus() {
        if (currentCredential == null) {
            return "未认证";
        }

        try {
            if (isCredentialValid()) {
                return "已认证 (有效)";
            } else {
                return "已认证 (需要刷新)";
            }
        } catch (Exception e) {
            return "认证状态未知";
        }
    }

    /**
     * 刷新访问令牌
     */
    public static boolean refreshToken() throws IOException {
        if (currentCredential != null && currentCredential.getRefreshToken() != null) {
            return currentCredential.refreshToken();
        }
        return false;
    }

    private static void deleteDirectory(File directory) {
        if (directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    deleteDirectory(file);
                }
            }
        }
        directory.delete();
    }

    public static String getCredentialsFilePath() {
        return CREDENTIALS_FILE_PATH;
    }
}